/**
 * This code is an extension of the original Scanner class from Java 6.
 */
package sk.upjs.paz;

import java.awt.EventQueue;
import java.io.*;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.nio.CharBuffer;
import java.text.*;
import java.util.*;
import java.util.regex.*;
import java.nio.channels.*;
import java.nio.charset.Charset;

import javax.swing.UIManager;

/**
 * Scanner that extends the original Java 6 Scanner with ability to visualize
 * its current state.
 * 
 * @author Frantisek Galcik
 */
public final class VisualScanner implements Iterator<String> {

	// Internal buffer used to hold input
	private CharBuffer buf;

	// Size of internal character buffer
	private static final int BUFFER_SIZE = 1024; // change to 1024;

	// The index into the buffer currently held by the Scanner
	private int position;

	// Internal matcher used for finding delimiters
	private Matcher matcher;

	// Pattern used to delimit tokens
	private Pattern delimPattern;

	// Pattern found in last hasNext operation
	private Pattern hasNextPattern;

	// Position after last hasNext operation
	private int hasNextPosition;

	// Result after last hasNext operation
	private String hasNextResult;

	// The input source
	private Readable source;

	// Boolean is true if source is done
	private boolean sourceClosed = false;

	// Boolean indicating more input is required
	private boolean needInput = false;

	// Boolean indicating if a delim has been skipped this operation
	private boolean skipped = false;

	// A store of a position that the scanner may fall back to
	private int savedScannerPosition = -1;

	// A cache of the last primitive type scanned
	private Object typeCache = null;

	// Boolean indicating if a match result is available
	private boolean matchValid = false;

	// Boolean indicating if this scanner has been closed
	private boolean closed = false;

	// The current radix used by this scanner
	private int radix = 10;

	// The default radix for this scanner
	private int defaultRadix = 10;

	// The locale used by this scanner
	private Locale locale = null;

	// A cache of the last few recently used Patterns
	private LRUCache<String, Pattern> patternCache = new LRUCache<String, Pattern>(7) {
		protected Pattern create(String s) {
			return Pattern.compile(s);
		}

		protected boolean hasName(Pattern p, String s) {
			return p.pattern().equals(s);
		}
	};

	// A holder of the last IOException encountered
	private IOException lastException;

	// A pattern for java whitespace
	private static Pattern WHITESPACE_PATTERN = Pattern.compile("\\p{javaWhitespace}+");

	// A pattern for any token
	private static Pattern FIND_ANY_PATTERN = Pattern.compile("(?s).*");

	// A pattern for non-ASCII digits
	private static Pattern NON_ASCII_DIGIT = Pattern.compile("[\\p{javaDigit}&&[^0-9]]");

	// Fields and methods to support scanning primitive types

	/**
	 * Locale dependent values used to scan numbers
	 */
	private String groupSeparator = "\\,";
	private String decimalSeparator = "\\.";
	private String nanString = "NaN";
	private String infinityString = "Infinity";
	private String positivePrefix = "";
	private String negativePrefix = "\\-";
	private String positiveSuffix = "";
	private String negativeSuffix = "";

	/**
	 * Fields and an accessor method to match booleans
	 */
	private static volatile Pattern boolPattern;
	private static final String BOOLEAN_PATTERN = "true|false";

	private static Pattern boolPattern() {
		Pattern bp = boolPattern;
		if (bp == null)
			boolPattern = bp = Pattern.compile(BOOLEAN_PATTERN, Pattern.CASE_INSENSITIVE);
		return bp;
	}

	/**
	 * Fields and methods to match bytes, shorts, ints, and longs
	 */
	private Pattern integerPattern;
	private String digits = "0123456789abcdefghijklmnopqrstuvwxyz";
	private String non0Digit = "[\\p{javaDigit}&&[^0]]";
	private int SIMPLE_GROUP_INDEX = 5;

	private String buildIntegerPatternString() {
		String radixDigits = digits.substring(0, radix);
		// \\p{javaDigit} is not guaranteed to be appropriate
		// here but what can we do? The final authority will be
		// whatever parse method is invoked, so ultimately the
		// Scanner will do the right thing
		String digit = "((?i)[" + radixDigits + "]|\\p{javaDigit})";
		String groupedNumeral = "(" + non0Digit + digit + "?" + digit + "?(" + groupSeparator + digit + digit + digit + ")+)";
		// digit++ is the possessive form which is necessary for reducing
		// backtracking that would otherwise cause unacceptable performance
		String numeral = "((" + digit + "++)|" + groupedNumeral + ")";
		String javaStyleInteger = "([-+]?(" + numeral + "))";
		String negativeInteger = negativePrefix + numeral + negativeSuffix;
		String positiveInteger = positivePrefix + numeral + positiveSuffix;
		return "(" + javaStyleInteger + ")|(" + positiveInteger + ")|(" + negativeInteger + ")";
	}

	private Pattern integerPattern() {
		if (integerPattern == null) {
			integerPattern = patternCache.forName(buildIntegerPatternString());
		}
		return integerPattern;
	}

	/**
	 * Fields and an accessor method to match line separators
	 */
	private static volatile Pattern separatorPattern;
	private static volatile Pattern linePattern;
	private static final String LINE_SEPARATOR_PATTERN = "\r\n|[\n\r  ]";
	private static final String LINE_PATTERN = ".*(" + LINE_SEPARATOR_PATTERN + ")|.+$";

	private static Pattern separatorPattern() {
		Pattern sp = separatorPattern;
		if (sp == null)
			separatorPattern = sp = Pattern.compile(LINE_SEPARATOR_PATTERN);
		return sp;
	}

	private static Pattern linePattern() {
		Pattern lp = linePattern;
		if (lp == null)
			linePattern = lp = Pattern.compile(LINE_PATTERN);
		return lp;
	}

	/**
	 * Fields and methods to match floats and doubles
	 */
	private Pattern floatPattern;
	private Pattern decimalPattern;

	private void buildFloatAndDecimalPattern() {
		// \\p{javaDigit} may not be perfect, see above
		String digit = "([0-9]|(\\p{javaDigit}))";
		String exponent = "([eE][+-]?" + digit + "+)?";
		String groupedNumeral = "(" + non0Digit + digit + "?" + digit + "?(" + groupSeparator + digit + digit + digit + ")+)";
		// Once again digit++ is used for performance, as above
		String numeral = "((" + digit + "++)|" + groupedNumeral + ")";
		String decimalNumeral = "(" + numeral + "|" + numeral + decimalSeparator + digit + "*+|" + decimalSeparator + digit + "++)";
		String nonNumber = "(NaN|" + nanString + "|Infinity|" + infinityString + ")";
		String positiveFloat = "(" + positivePrefix + decimalNumeral + positiveSuffix + exponent + ")";
		String negativeFloat = "(" + negativePrefix + decimalNumeral + negativeSuffix + exponent + ")";
		String decimal = "(([-+]?" + decimalNumeral + exponent + ")|" + positiveFloat + "|" + negativeFloat + ")";
		String hexFloat = "[-+]?0[xX][0-9a-fA-F]*\\.[0-9a-fA-F]+([pP][-+]?[0-9]+)?";
		String positiveNonNumber = "(" + positivePrefix + nonNumber + positiveSuffix + ")";
		String negativeNonNumber = "(" + negativePrefix + nonNumber + negativeSuffix + ")";
		String signedNonNumber = "(([-+]?" + nonNumber + ")|" + positiveNonNumber + "|" + negativeNonNumber + ")";
		floatPattern = Pattern.compile(decimal + "|" + hexFloat + "|" + signedNonNumber);
		decimalPattern = Pattern.compile(decimal);
	}

	private Pattern floatPattern() {
		if (floatPattern == null) {
			buildFloatAndDecimalPattern();
		}
		return floatPattern;
	}

	private Pattern decimalPattern() {
		if (decimalPattern == null) {
			buildFloatAndDecimalPattern();
		}
		return decimalPattern;
	}

	// Constructors

	/**
	 * Constructs a <code>Scanner</code> that returns values scanned from the
	 * specified source delimited by the specified pattern.
	 * 
	 * @param source
	 *            A character source implementing the Readable interface
	 * @param pattern
	 *            A delimiting pattern
	 * @return A scanner with the specified source and pattern
	 */
	private VisualScanner(Readable source, Pattern pattern) {
		if (source == null)
			throw new NullPointerException("source");
		if (pattern == null)
			throw new NullPointerException("pattern");
		this.source = source;
		delimPattern = pattern;
		buf = CharBuffer.allocate(BUFFER_SIZE);
		buf.limit(0);
		matcher = delimPattern.matcher(buf);
		matcher.useTransparentBounds(true);
		matcher.useAnchoringBounds(false);
		useLocale(Locale.getDefault());
		sourceDescription = source.getClass().getName();
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified source.
	 * 
	 * @param source
	 *            A character source implementing the {@link Readable} interface
	 */
	public VisualScanner(Readable source) {
		this(source, WHITESPACE_PATTERN);
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified input stream. Bytes from the stream are converted into
	 * characters using the underlying platform's
	 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
	 * 
	 * @param source
	 *            An input stream to be scanned
	 */
	public VisualScanner(InputStream source) {
		this(new InputStreamReader(source), WHITESPACE_PATTERN);
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified input stream. Bytes from the stream are converted into
	 * characters using the specified charset.
	 * 
	 * @param source
	 *            An input stream to be scanned
	 * @param charsetName
	 *            The encoding type used to convert bytes from the stream into
	 *            characters to be scanned
	 * @throws IllegalArgumentException
	 *             if the specified character set does not exist
	 */
	public VisualScanner(InputStream source, String charsetName) {
		this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
	}

	private static Readable makeReadable(InputStream source, String charsetName) {
		if (source == null)
			throw new NullPointerException("source");
		InputStreamReader isr = null;
		try {
			isr = new InputStreamReader(source, charsetName);
		} catch (UnsupportedEncodingException uee) {
			IllegalArgumentException iae = new IllegalArgumentException();
			iae.initCause(uee);
			throw iae;
		}
		return isr;
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified file. Bytes from the file are converted into characters
	 * using the underlying platform's
	 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
	 * 
	 * @param source
	 *            A file to be scanned
	 * @throws FileNotFoundException
	 *             if source is not found
	 */
	public VisualScanner(File source) throws FileNotFoundException {
		this((ReadableByteChannel) (new FileInputStream(source).getChannel()));
		sourceDescription = "File(\"" + source.toString() + "\")";
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified file. Bytes from the file are converted into characters
	 * using the specified charset.
	 * 
	 * @param source
	 *            A file to be scanned
	 * @param charsetName
	 *            The encoding type used to convert bytes from the file into
	 *            characters to be scanned
	 * @throws FileNotFoundException
	 *             if source is not found
	 * @throws IllegalArgumentException
	 *             if the specified encoding is not found
	 */
	public VisualScanner(File source, String charsetName) throws FileNotFoundException {
		this((ReadableByteChannel) (new FileInputStream(source).getChannel()), charsetName);
		sourceDescription = "File(\"" + source.toString() + "\"), charset: " + charsetName;
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified string.
	 * 
	 * @param source
	 *            A string to scan
	 */
	public VisualScanner(String source) {
		this(new StringReader(source), WHITESPACE_PATTERN);
		sourceDescription = "String(\"" + source + "\")";
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified channel. Bytes from the source are converted into
	 * characters using the underlying platform's
	 * {@linkplain java.nio.charset.Charset#defaultCharset() default charset}.
	 * 
	 * @param source
	 *            A channel to scan
	 */
	public VisualScanner(ReadableByteChannel source) {
		this(makeReadable(source), WHITESPACE_PATTERN);
	}

	private static Readable makeReadable(ReadableByteChannel source) {
		if (source == null)
			throw new NullPointerException("source");
		String defaultCharsetName = java.nio.charset.Charset.defaultCharset().name();
		return Channels.newReader(source, java.nio.charset.Charset.defaultCharset().name());
	}

	/**
	 * Constructs a new <code>Scanner</code> that produces values scanned from
	 * the specified channel. Bytes from the source are converted into
	 * characters using the specified charset.
	 * 
	 * @param source
	 *            A channel to scan
	 * @param charsetName
	 *            The encoding type used to convert bytes from the channel into
	 *            characters to be scanned
	 * @throws IllegalArgumentException
	 *             if the specified character set does not exist
	 */
	public VisualScanner(ReadableByteChannel source, String charsetName) {
		this(makeReadable(source, charsetName), WHITESPACE_PATTERN);
	}

	private static Readable makeReadable(ReadableByteChannel source, String charsetName) {
		if (source == null)
			throw new NullPointerException("source");
		if (!Charset.isSupported(charsetName))
			throw new IllegalArgumentException(charsetName);
		return Channels.newReader(source, charsetName);
	}

	// Private primitives used to support scanning

	private void saveState() {
		savedScannerPosition = position;
	}

	private void revertState() {
		this.position = savedScannerPosition;
		savedScannerPosition = -1;
		skipped = false;
	}

	private boolean revertState(boolean b) {
		this.position = savedScannerPosition;
		savedScannerPosition = -1;
		skipped = false;
		return b;
	}

	private void cacheResult() {
		hasNextResult = matcher.group();
		hasNextPosition = matcher.end();
		hasNextPattern = matcher.pattern();
	}

	private void cacheResult(String result) {
		hasNextResult = result;
		hasNextPosition = matcher.end();
		hasNextPattern = matcher.pattern();
	}

	// Clears both regular cache and type cache
	private void clearCaches() {
		hasNextPattern = null;
		typeCache = null;
	}

	// Also clears the both the regular cache and the type cache
	private String getCachedResult() {
		position = hasNextPosition;
		hasNextPattern = null;
		typeCache = null;
		return hasNextResult;
	}

	// Also clears the both the regular cache and the type cache
	private void useTypeCache() {
		if (closed)
			throw new IllegalStateException("Scanner closed");
		position = hasNextPosition;
		hasNextPattern = null;
		typeCache = null;
	}

	// Tries to read more input. May block.
	private void readInput() {
		if (buf.limit() == buf.capacity())
			makeSpace();

		// Prepare to receive data
		int p = buf.position();
		buf.position(buf.limit());
		buf.limit(buf.capacity());

		int n = 0;
		try {
			n = source.read(buf);
		} catch (IOException ioe) {
			lastException = ioe;
			n = -1;
		}

		if (n == -1) {
			sourceClosed = true;
			needInput = false;
		}

		if (n > 0)
			needInput = false;

		// Restore current position and limit for reading
		buf.limit(buf.position());
		buf.position(p);
	}

	// After this method is called there will either be an exception
	// or else there will be space in the buffer
	private boolean makeSpace() {
		clearCaches();
		int offset = savedScannerPosition == -1 ? position : savedScannerPosition;
		buf.position(offset);
		// Gain space by compacting buffer
		if (offset > 0) {
			buf.compact();
			translateSavedIndexes(offset);
			position -= offset;
			buf.flip();
			return true;
		}
		// Gain space by growing buffer
		int newSize = buf.capacity() * 2;
		CharBuffer newBuf = CharBuffer.allocate(newSize);
		newBuf.put(buf);
		newBuf.flip();
		translateSavedIndexes(offset);
		position -= offset;
		buf = newBuf;
		matcher.reset(buf);
		return true;
	}

	// When a buffer compaction/reallocation occurs the saved indexes must
	// be modified appropriately
	private void translateSavedIndexes(int offset) {
		if (savedScannerPosition != -1)
			savedScannerPosition -= offset;
	}

	// If we are at the end of input then NoSuchElement;
	// If there is still input left then InputMismatch
	private void throwFor() {
		skipped = false;
		if ((sourceClosed) && (position == buf.limit()))
			throw new NoSuchElementException();
		else
			throw new InputMismatchException();
	}

	// Returns true if a complete token or partial token is in the buffer.
	// It is not necessary to find a complete token since a partial token
	// means that there will be another token with or without more input.
	private boolean hasTokenInBuffer() {
		matchValid = false;
		matcher.usePattern(delimPattern);
		matcher.region(position, buf.limit());

		// Skip delims first
		if (matcher.lookingAt())
			position = matcher.end();

		// If we are sitting at the end, no more tokens in buffer
		if (position == buf.limit())
			return false;

		return true;
	}

	/*
	 * Returns a "complete token" that matches the specified pattern
	 * 
	 * A token is complete if surrounded by delims; a partial token is prefixed
	 * by delims but not postfixed by them
	 * 
	 * The position is advanced to the end of that complete token
	 * 
	 * Pattern == null means accept any token at all
	 * 
	 * Triple return: 1. valid string means it was found 2. null with
	 * needInput=false means we won't ever find it 3. null with needInput=true
	 * means try again after readInput
	 */
	private String getCompleteTokenInBuffer(Pattern pattern) {
		matchValid = false;

		// Skip delims first
		matcher.usePattern(delimPattern);
		if (!skipped) { // Enforcing only one skip of leading delims
			matcher.region(position, buf.limit());
			if (matcher.lookingAt()) {
				// If more input could extend the delimiters then we must wait
				// for more input
				if (matcher.hitEnd() && !sourceClosed) {
					needInput = true;
					return null;
				}
				// The delims were whole and the matcher should skip them
				skipped = true;
				position = matcher.end();
			}
		}

		// If we are sitting at the end, no more tokens in buffer
		if (position == buf.limit()) {
			if (sourceClosed)
				return null;
			needInput = true;
			return null;
		}

		// Must look for next delims. Simply attempting to match the
		// pattern at this point may find a match but it might not be
		// the first longest match because of missing input, or it might
		// match a partial token instead of the whole thing.

		// Then look for next delims
		matcher.region(position, buf.limit());
		boolean foundNextDelim = matcher.find();
		if (foundNextDelim && (matcher.end() == position)) {
			// Zero length delimiter match; we should find the next one
			// using the automatic advance past a zero length match;
			// Otherwise we have just found the same one we just skipped
			foundNextDelim = matcher.find();
		}
		if (foundNextDelim) {
			// In the rare case that more input could cause the match
			// to be lost and there is more input coming we must wait
			// for more input. Note that hitting the end is okay as long
			// as the match cannot go away. It is the beginning of the
			// next delims we want to be sure about, we don't care if
			// they potentially extend further.
			if (matcher.requireEnd() && !sourceClosed) {
				needInput = true;
				return null;
			}
			int tokenEnd = matcher.start();
			// There is a complete token.
			if (pattern == null) {
				// Must continue with match to provide valid MatchResult
				pattern = FIND_ANY_PATTERN;
			}
			// Attempt to match against the desired pattern
			matcher.usePattern(pattern);
			matcher.region(position, tokenEnd);
			if (matcher.matches()) {
				String s = matcher.group();
				position = matcher.end();
				return s;
			} else { // Complete token but it does not match
				return null;
			}
		}

		// If we can't find the next delims but no more input is coming,
		// then we can treat the remainder as a whole token
		if (sourceClosed) {
			if (pattern == null) {
				// Must continue with match to provide valid MatchResult
				pattern = FIND_ANY_PATTERN;
			}
			// Last token; Match the pattern here or throw
			matcher.usePattern(pattern);
			matcher.region(position, buf.limit());
			if (matcher.matches()) {
				String s = matcher.group();
				position = matcher.end();
				return s;
			}
			// Last piece does not match
			return null;
		}

		// There is a partial token in the buffer; must read more
		// to complete it
		needInput = true;
		return null;
	}

	// Finds the specified pattern in the buffer up to horizon.
	// Returns a match for the specified input pattern.
	private String findPatternInBuffer(Pattern pattern, int horizon) {
		matchValid = false;
		matcher.usePattern(pattern);
		int bufferLimit = buf.limit();
		int horizonLimit = -1;
		int searchLimit = bufferLimit;
		if (horizon > 0) {
			horizonLimit = position + horizon;
			if (horizonLimit < bufferLimit)
				searchLimit = horizonLimit;
		}
		matcher.region(position, searchLimit);
		if (matcher.find()) {
			if (matcher.hitEnd() && (!sourceClosed)) {
				// The match may be longer if didn't hit horizon or real end
				if (searchLimit != horizonLimit) {
					// Hit an artificial end; try to extend the match
					needInput = true;
					return null;
				}
				// The match could go away depending on what is next
				if ((searchLimit == horizonLimit) && matcher.requireEnd()) {
					// Rare case: we hit the end of input and it happens
					// that it is at the horizon and the end of input is
					// required for the match.
					needInput = true;
					return null;
				}
			}
			// Did not hit end, or hit real end, or hit horizon
			position = matcher.end();
			return matcher.group();
		}

		if (sourceClosed)
			return null;

		// If there is no specified horizon, or if we have not searched
		// to the specified horizon yet, get more input
		if ((horizon == 0) || (searchLimit != horizonLimit))
			needInput = true;
		return null;
	}

	// Returns a match for the specified input pattern anchored at
	// the current position
	private String matchPatternInBuffer(Pattern pattern) {
		matchValid = false;
		matcher.usePattern(pattern);
		matcher.region(position, buf.limit());
		if (matcher.lookingAt()) {
			if (matcher.hitEnd() && (!sourceClosed)) {
				// Get more input and try again
				needInput = true;
				return null;
			}
			position = matcher.end();
			return matcher.group();
		}

		if (sourceClosed)
			return null;

		// Read more to find pattern
		needInput = true;
		return null;
	}

	// Throws if the scanner is closed
	private void ensureOpen() {
		if (closed)
			throw new IllegalStateException("Scanner closed");
	}

	// Public methods

	/**
	 * Closes this scanner.
	 * 
	 * <p>
	 * If this scanner has not yet been closed then if its underlying
	 * {@linkplain java.lang.Readable readable} also implements the
	 * {@link java.io.Closeable} interface then the readable's <tt>close</tt>
	 * method will be invoked. If this scanner is already closed then invoking
	 * this method will have no effect.
	 * 
	 * <p>
	 * Attempting to perform search operations after a scanner has been closed
	 * will result in an {@link IllegalStateException}.
	 * 
	 */
	public void close() {
		try {
			initiateMethodCall("close");
			if (closed)
				return;
			if (source instanceof Closeable) {
				try {
					((Closeable) source).close();
				} catch (IOException ioe) {
					lastException = ioe;
				}
			}
			sourceClosed = true;
			source = null;
			closed = true;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns the <code>IOException</code> last thrown by this
	 * <code>Scanner</code>'s underlying <code>Readable</code>. This method
	 * returns <code>null</code> if no such exception exists.
	 * 
	 * @return the last exception thrown by this scanner's readable
	 */
	public IOException ioException() {
		return lastException;
	}

	/**
	 * Returns the <code>Pattern</code> this <code>Scanner</code> is currently
	 * using to match delimiters.
	 * 
	 * @return this scanner's delimiting pattern.
	 */
	public Pattern delimiter() {
		return delimPattern;
	}

	/**
	 * Sets this scanner's delimiting pattern to the specified pattern.
	 * 
	 * @param pattern
	 *            A delimiting pattern
	 * @return this scanner
	 */
	public VisualScanner useDelimiter(Pattern pattern) {
		delimPattern = pattern;
		return this;
	}

	/**
	 * Sets this scanner's delimiting pattern to a pattern constructed from the
	 * specified <code>String</code>.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>useDelimiter(pattern)</tt>
	 * behaves in exactly the same way as the invocation
	 * <tt>useDelimiter(Pattern.compile(pattern))</tt>.
	 * 
	 * <p>
	 * Invoking the {@link #reset} method will set the scanner's delimiter to
	 * the <a href= "#default-delimiter">default</a>.
	 * 
	 * @param pattern
	 *            A string specifying a delimiting pattern
	 * @return this scanner
	 */
	public VisualScanner useDelimiter(String pattern) {
		delimPattern = patternCache.forName(pattern);
		return this;
	}

	/**
	 * Returns this scanner's locale.
	 * 
	 * <p>
	 * A scanner's locale affects many elements of its default primitive
	 * matching regular expressions; see <a href= "#localized-numbers">localized
	 * numbers</a> above.
	 * 
	 * @return this scanner's locale
	 */
	public Locale locale() {
		return this.locale;
	}

	/**
	 * Sets this scanner's locale to the specified locale.
	 * 
	 * <p>
	 * A scanner's locale affects many elements of its default primitive
	 * matching regular expressions; see <a href= "#localized-numbers">localized
	 * numbers</a> above.
	 * 
	 * <p>
	 * Invoking the {@link #reset} method will set the scanner's locale to the
	 * <a href= "#initial-locale">initial locale</a>.
	 * 
	 * @param locale
	 *            A string specifying the locale to use
	 * @return this scanner
	 */
	public VisualScanner useLocale(Locale locale) {
		if (locale.equals(this.locale))
			return this;

		this.locale = locale;
		DecimalFormat df = (DecimalFormat) NumberFormat.getNumberInstance(locale);
		DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(locale);

		// These must be literalized to avoid collision with regex
		// metacharacters such as dot or parenthesis
		groupSeparator = "\\" + dfs.getGroupingSeparator();
		decimalSeparator = "\\" + dfs.getDecimalSeparator();

		// Quoting the nonzero length locale-specific things
		// to avoid potential conflict with metacharacters
		nanString = "\\Q" + dfs.getNaN() + "\\E";
		infinityString = "\\Q" + dfs.getInfinity() + "\\E";
		positivePrefix = df.getPositivePrefix();
		if (positivePrefix.length() > 0)
			positivePrefix = "\\Q" + positivePrefix + "\\E";
		negativePrefix = df.getNegativePrefix();
		if (negativePrefix.length() > 0)
			negativePrefix = "\\Q" + negativePrefix + "\\E";
		positiveSuffix = df.getPositiveSuffix();
		if (positiveSuffix.length() > 0)
			positiveSuffix = "\\Q" + positiveSuffix + "\\E";
		negativeSuffix = df.getNegativeSuffix();
		if (negativeSuffix.length() > 0)
			negativeSuffix = "\\Q" + negativeSuffix + "\\E";

		// Force rebuilding and recompilation of locale dependent
		// primitive patterns
		integerPattern = null;
		floatPattern = null;

		return this;
	}

	/**
	 * Returns this scanner's default radix.
	 * 
	 * <p>
	 * A scanner's radix affects elements of its default number matching regular
	 * expressions; see <a href= "#localized-numbers">localized numbers</a>
	 * above.
	 * 
	 * @return the default radix of this scanner
	 */
	public int radix() {
		return this.defaultRadix;
	}

	/**
	 * Sets this scanner's default radix to the specified radix.
	 * 
	 * <p>
	 * A scanner's radix affects elements of its default number matching regular
	 * expressions; see <a href= "#localized-numbers">localized numbers</a>
	 * above.
	 * 
	 * <p>
	 * If the radix is less than <code>Character.MIN_RADIX</code> or greater
	 * than <code>Character.MAX_RADIX</code>, then an
	 * <code>IllegalArgumentException</code> is thrown.
	 * 
	 * <p>
	 * Invoking the {@link #reset} method will set the scanner's radix to
	 * <code>10</code>.
	 * 
	 * @param radix
	 *            The radix to use when scanning numbers
	 * @return this scanner
	 * @throws IllegalArgumentException
	 *             if radix is out of range
	 */
	public VisualScanner useRadix(int radix) {
		if ((radix < Character.MIN_RADIX) || (radix > Character.MAX_RADIX))
			throw new IllegalArgumentException("radix:" + radix);

		if (this.defaultRadix == radix)
			return this;
		this.defaultRadix = radix;
		// Force rebuilding and recompilation of radix dependent patterns
		integerPattern = null;
		return this;
	}

	// The next operation should occur in the specified radix but
	// the default is left untouched.
	private void setRadix(int radix) {
		if (this.radix != radix) {
			// Force rebuilding and recompilation of radix dependent patterns
			integerPattern = null;
			this.radix = radix;
		}
	}

	/**
	 * Returns the match result of the last scanning operation performed by this
	 * scanner. This method throws <code>IllegalStateException</code> if no
	 * match has been performed, or if the last match was not successful.
	 * 
	 * <p>
	 * The various <code>next</code>methods of <code>Scanner</code> make a match
	 * result available if they complete without throwing an exception. For
	 * instance, after an invocation of the {@link #nextInt} method that
	 * returned an int, this method returns a <code>MatchResult</code> for the
	 * search of the <a href="#Integer-regex"><i>Integer</i></a> regular
	 * expression defined above. Similarly the {@link #findInLine},
	 * {@link #findWithinHorizon}, and {@link #skip} methods will make a match
	 * available if they succeed.
	 * 
	 * @return a match result for the last match operation
	 * @throws IllegalStateException
	 *             If no match result is available
	 */
	public MatchResult match() {
		if (!matchValid)
			throw new IllegalStateException("No match result available");
		return matcher.toMatchResult();
	}

	/**
	 * <p>
	 * Returns the string representation of this <code>Scanner</code>. The
	 * string representation of a <code>Scanner</code> contains information that
	 * may be useful for debugging. The exact format is unspecified.
	 * 
	 * @return The string representation of this scanner
	 */
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append("java.util.Scanner");
		sb.append("[delimiters=" + delimPattern + "]");
		sb.append("[position=" + position + "]");
		sb.append("[match valid=" + matchValid + "]");
		sb.append("[need input=" + needInput + "]");
		sb.append("[source closed=" + sourceClosed + "]");
		sb.append("[skipped=" + skipped + "]");
		sb.append("[group separator=" + groupSeparator + "]");
		sb.append("[decimal separator=" + decimalSeparator + "]");
		sb.append("[positive prefix=" + positivePrefix + "]");
		sb.append("[negative prefix=" + negativePrefix + "]");
		sb.append("[positive suffix=" + positiveSuffix + "]");
		sb.append("[negative suffix=" + negativeSuffix + "]");
		sb.append("[NaN string=" + nanString + "]");
		sb.append("[infinity string=" + infinityString + "]");
		return sb.toString();
	}

	/**
	 * Returns true if this scanner has another token in its input. This method
	 * may block while waiting for input to scan. The scanner does not advance
	 * past any input.
	 * 
	 * @return true if and only if this scanner has another token
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 * @see java.util.Iterator
	 */
	public boolean hasNext() {
		try {
			initiateMethodCall("hasNext()");
			ensureOpen();
			saveState();
			while (!sourceClosed) {
				if (hasTokenInBuffer())
					return revertState(true);
				readInput();
			}
			boolean result = hasTokenInBuffer();
			return revertState(result);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Finds and returns the next complete token from this scanner. A complete
	 * token is preceded and followed by input that matches the delimiter
	 * pattern. This method may block while waiting for input to scan, even if a
	 * previous invocation of {@link #hasNext} returned <code>true</code>.
	 * 
	 * @return the next token
	 * @throws NoSuchElementException
	 *             if no more tokens are available
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 * @see java.util.Iterator
	 */
	public String next() {
		try {
			initiateMethodCall("next()");
			ensureOpen();
			clearCaches();

			while (true) {
				String token = getCompleteTokenInBuffer(null);
				if (token != null) {
					matchValid = true;
					skipped = false;
					return token;
				}
				if (needInput)
					readInput();
				else
					throwFor();
			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * The remove operation is not supported by this implementation of
	 * <code>Iterator</code>.
	 * 
	 * @throws UnsupportedOperationException
	 *             if this method is invoked.
	 * @see java.util.Iterator
	 */
	public void remove() {
		throw new UnsupportedOperationException();
	}

	/**
	 * Returns true if the next token matches the pattern constructed from the
	 * specified string. The scanner does not advance past any input.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>hasNext(pattern)</tt>
	 * behaves in exactly the same way as the invocation
	 * <tt>hasNext(Pattern.compile(pattern))</tt>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to scan
	 * @return true if and only if this scanner has another token matching the
	 *         specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNext(String pattern) {
		return hasNext(patternCache.forName(pattern));
	}

	/**
	 * Returns the next token if it matches the pattern constructed from the
	 * specified string. If the match is successful, the scanner advances past
	 * the input that matched the pattern.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>next(pattern)</tt> behaves
	 * in exactly the same way as the invocation
	 * <tt>next(Pattern.compile(pattern))</tt>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to scan
	 * @return the next token
	 * @throws NoSuchElementException
	 *             if no such tokens are available
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public String next(String pattern) {
		return next(patternCache.forName(pattern));
	}

	/**
	 * Returns true if the next complete token matches the specified pattern. A
	 * complete token is prefixed and postfixed by input that matches the
	 * delimiter pattern. This method may block while waiting for input. The
	 * scanner does not advance past any input.
	 * 
	 * @param pattern
	 *            the pattern to scan for
	 * @return true if and only if this scanner has another token matching the
	 *         specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNext(Pattern pattern) {
		try {
			initiateMethodCall("hasNext(" + pattern + ")");
			ensureOpen();
			if (pattern == null)
				throw new NullPointerException();
			hasNextPattern = null;
			saveState();

			while (true) {
				if (getCompleteTokenInBuffer(pattern) != null) {
					matchValid = true;
					cacheResult();
					return revertState(true);
				}
				if (needInput)
					readInput();
				else
					return revertState(false);
			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns the next token if it matches the specified pattern. This method
	 * may block while waiting for input to scan, even if a previous invocation
	 * of {@link #hasNext(Pattern)} returned <code>true</code>. If the match is
	 * successful, the scanner advances past the input that matched the pattern.
	 * 
	 * @param pattern
	 *            the pattern to scan for
	 * @return the next token
	 * @throws NoSuchElementException
	 *             if no more tokens are available
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public String next(Pattern pattern) {
		try {
			initiateMethodCall("next(" + pattern + ")");
			ensureOpen();
			if (pattern == null)
				throw new NullPointerException();

			// Did we already find this pattern?
			if (hasNextPattern == pattern)
				return getCachedResult();
			clearCaches();

			// Search for the pattern
			while (true) {
				String token = getCompleteTokenInBuffer(pattern);
				if (token != null) {
					matchValid = true;
					skipped = false;
					return token;
				}
				if (needInput)
					readInput();
				else
					throwFor();
			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if there is another line in the input of this scanner. This
	 * method may block while waiting for input. The scanner does not advance
	 * past any input.
	 * 
	 * @return true if and only if this scanner has another line of input
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextLine() {
		try {
			initiateMethodCall("hasNextLine()");
			saveState();

			String result = findWithinHorizon(linePattern(), 0);
			if (result != null) {
				MatchResult mr = this.match();
				String lineSep = mr.group(1);
				if (lineSep != null) {
					result = result.substring(0, result.length() - lineSep.length());
					cacheResult(result);

				} else {
					cacheResult();
				}
			}
			revertState();
			return (result != null);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Advances this scanner past the current line and returns the input that
	 * was skipped.
	 * 
	 * This method returns the rest of the current line, excluding any line
	 * separator at the end. The position is set to the beginning of the next
	 * line.
	 * 
	 * <p>
	 * Since this method continues to search through the input looking for a
	 * line separator, it may buffer all of the input searching for the line to
	 * skip if no line separators are present.
	 * 
	 * @return the line that was skipped
	 * @throws NoSuchElementException
	 *             if no line was found
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public String nextLine() {
		try {
			initiateMethodCall("nextLine()");
			if (hasNextPattern == linePattern())
				return getCachedResult();
			clearCaches();

			String result = findWithinHorizon(linePattern, 0);
			if (result == null)
				throw new NoSuchElementException("No line found");
			MatchResult mr = this.match();
			String lineSep = mr.group(1);
			if (lineSep != null)
				result = result.substring(0, result.length() - lineSep.length());
			if (result == null)
				throw new NoSuchElementException();
			else
				return result;
		} finally {
			finalizeMethodCall();
		}
	}

	// Public methods that ignore delimiters

	/**
	 * Attempts to find the next occurrence of a pattern constructed from the
	 * specified string, ignoring delimiters.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>findInLine(pattern)</tt>
	 * behaves in exactly the same way as the invocation
	 * <tt>findInLine(Pattern.compile(pattern))</tt>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to search for
	 * @return the text that matched the specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public String findInLine(String pattern) {
		return findInLine(patternCache.forName(pattern));
	}

	/**
	 * Attempts to find the next occurrence of the specified pattern ignoring
	 * delimiters. If the pattern is found before the next line separator, the
	 * scanner advances past the input that matched and returns the string that
	 * matched the pattern. If no such pattern is detected in the input up to
	 * the next line separator, then <code>null</code> is returned and the
	 * scanner's position is unchanged. This method may block waiting for input
	 * that matches the pattern.
	 * 
	 * <p>
	 * Since this method continues to search through the input looking for the
	 * specified pattern, it may buffer all of the input searching for the
	 * desired token if no line separators are present.
	 * 
	 * @param pattern
	 *            the pattern to scan for
	 * @return the text that matched the specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public String findInLine(Pattern pattern) {
		try {
			initiateMethodCall("findInLine(" + pattern + ")");
			ensureOpen();
			if (pattern == null)
				throw new NullPointerException();
			clearCaches();
			// Expand buffer to include the next newline or end of input
			int endPosition = 0;
			saveState();
			while (true) {
				String token = findPatternInBuffer(separatorPattern(), 0);
				if (token != null) {
					endPosition = matcher.start();
					break; // up to next newline
				}
				if (needInput) {
					readInput();
				} else {
					endPosition = buf.limit();
					break; // up to end of input
				}
			}
			revertState();
			int horizonForLine = endPosition - position;
			// If there is nothing between the current pos and the next
			// newline simply return null, invoking findWithinHorizon
			// with "horizon=0" will scan beyond the line bound.
			if (horizonForLine == 0)
				return null;
			// Search for the pattern
			return findWithinHorizon(pattern, horizonForLine);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Attempts to find the next occurrence of a pattern constructed from the
	 * specified string, ignoring delimiters.
	 * 
	 * <p>
	 * An invocation of this method of the form
	 * <tt>findWithinHorizon(pattern)</tt> behaves in exactly the same way as
	 * the invocation
	 * <tt>findWithinHorizon(Pattern.compile(pattern, horizon))</tt>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to search for
	 * @return the text that matched the specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 * @throws IllegalArgumentException
	 *             if horizon is negative
	 */
	public String findWithinHorizon(String pattern, int horizon) {
		return findWithinHorizon(patternCache.forName(pattern), horizon);
	}

	/**
	 * Attempts to find the next occurrence of the specified pattern.
	 * 
	 * <p>
	 * This method searches through the input up to the specified search
	 * horizon, ignoring delimiters. If the pattern is found the scanner
	 * advances past the input that matched and returns the string that matched
	 * the pattern. If no such pattern is detected then the null is returned and
	 * the scanner's position remains unchanged. This method may block waiting
	 * for input that matches the pattern.
	 * 
	 * <p>
	 * A scanner will never search more than <code>horizon</code> code points
	 * beyond its current position. Note that a match may be clipped by the
	 * horizon; that is, an arbitrary match result may have been different if
	 * the horizon had been larger. The scanner treats the horizon as a
	 * transparent, non-anchoring bound (see
	 * {@link Matcher#useTransparentBounds} and
	 * {@link Matcher#useAnchoringBounds}).
	 * 
	 * <p>
	 * If horizon is <code>0</code>, then the horizon is ignored and this method
	 * continues to search through the input looking for the specified pattern
	 * without bound. In this case it may buffer all of the input searching for
	 * the pattern.
	 * 
	 * <p>
	 * If horizon is negative, then an IllegalArgumentException is thrown.
	 * 
	 * @param pattern
	 *            the pattern to scan for
	 * @return the text that matched the specified pattern
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 * @throws IllegalArgumentException
	 *             if horizon is negative
	 */
	public String findWithinHorizon(Pattern pattern, int horizon) {
		try {
			initiateMethodCall("findWithinHorizon(" + pattern + ", " + horizon + ")");
			ensureOpen();
			if (pattern == null)
				throw new NullPointerException();
			if (horizon < 0)
				throw new IllegalArgumentException("horizon < 0");
			clearCaches();

			// Search for the pattern
			while (true) {
				String token = findPatternInBuffer(pattern, horizon);
				if (token != null) {
					matchValid = true;
					return token;
				}
				if (needInput)
					readInput();
				else
					break; // up to end of input
			}
			return null;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Skips input that matches the specified pattern, ignoring delimiters. This
	 * method will skip input if an anchored match of the specified pattern
	 * succeeds.
	 * 
	 * <p>
	 * If a match to the specified pattern is not found at the current position,
	 * then no input is skipped and a <tt>NoSuchElementException</tt> is thrown.
	 * 
	 * <p>
	 * Since this method seeks to match the specified pattern starting at the
	 * scanner's current position, patterns that can match a lot of input (".*",
	 * for example) may cause the scanner to buffer a large amount of input.
	 * 
	 * <p>
	 * Note that it is possible to skip something without risking a
	 * <code>NoSuchElementException</code> by using a pattern that can match
	 * nothing, e.g., <code>sc.skip("[ \t]*")</code>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to skip over
	 * @return this scanner
	 * @throws NoSuchElementException
	 *             if the specified pattern is not found
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public VisualScanner skip(Pattern pattern) {
		try {
			initiateMethodCall("skip(" + pattern + ")");
			ensureOpen();
			if (pattern == null)
				throw new NullPointerException();
			clearCaches();

			// Search for the pattern
			while (true) {
				String token = matchPatternInBuffer(pattern);
				if (token != null) {
					matchValid = true;
					position = matcher.end();
					return this;
				}
				if (needInput)
					readInput();
				else
					throw new NoSuchElementException();
			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Skips input that matches a pattern constructed from the specified string.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>skip(pattern)</tt> behaves
	 * in exactly the same way as the invocation
	 * <tt>skip(Pattern.compile(pattern))</tt>.
	 * 
	 * @param pattern
	 *            a string specifying the pattern to skip over
	 * @return this scanner
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public VisualScanner skip(String pattern) {
		return skip(patternCache.forName(pattern));
	}

	// Convenience methods for scanning primitives

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a boolean value using a case insensitive pattern created from the
	 * string "true|false". The scanner does not advance past the input that
	 * matched.
	 * 
	 * @return true if and only if this scanner's next token is a valid boolean
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextBoolean() {
		try {
			initiateMethodCall("hasNextBoolean()");
			return hasNext(boolPattern());
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input into a boolean value and returns that
	 * value. This method will throw <code>InputMismatchException</code> if the
	 * next token cannot be translated into a valid boolean value. If the match
	 * is successful, the scanner advances past the input that matched.
	 * 
	 * @return the boolean scanned from the input
	 * @throws InputMismatchException
	 *             if the next token is not a valid boolean
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean nextBoolean() {
		try {
			initiateMethodCall("nextBoolean()");
			clearCaches();
			return Boolean.parseBoolean(next(boolPattern()));
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a byte value in the default radix using the {@link #nextByte} method.
	 * The scanner does not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid byte
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextByte() {
		try {
			initiateMethodCall("hasNextByte()");
			return hasNextByte(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a byte value in the specified radix using the {@link #nextByte}
	 * method. The scanner does not advance past any input.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as a byte value
	 * @return true if and only if this scanner's next token is a valid byte
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextByte(int radix) {
		try {
			initiateMethodCall("hasNextByte(" + radix + ")");
			setRadix(radix);
			boolean result = hasNext(integerPattern());
			if (result) { // Cache it
				try {
					String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? processIntegerToken(hasNextResult) : hasNextResult;
					typeCache = Byte.parseByte(s, radix);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>byte</tt>.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>nextByte()</tt> behaves in
	 * exactly the same way as the invocation <tt>nextByte(radix)</tt>, where
	 * <code>radix</code> is the default radix of this scanner.
	 * 
	 * @return the <tt>byte</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public byte nextByte() {
		try {
			initiateMethodCall("nextByte()");
			return nextByte(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>byte</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid byte value as described below. If the translation
	 * is successful, the scanner advances past the input that matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Integer-regex"><i>Integer</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>byte</tt> value as if by removing all locale specific prefixes, group
	 * separators, and locale specific suffixes, then mapping non-ASCII digits
	 * into ASCII digits via {@link Character#digit Character.digit}, prepending
	 * a negative sign (-) if the locale specific negative prefixes and suffixes
	 * were present, and passing the resulting string to
	 * {@link Byte#parseByte(String, int) Byte.parseByte} with the specified
	 * radix.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as a byte value
	 * @return the <tt>byte</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public byte nextByte(int radix) {
		try {
			initiateMethodCall("nextByte(" + radix + ")");

			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Byte) && this.radix == radix) {
				byte val = ((Byte) typeCache).byteValue();
				useTypeCache();
				return val;
			}
			setRadix(radix);
			clearCaches();
			// Search for next byte
			try {
				String s = next(integerPattern());
				if (matcher.group(SIMPLE_GROUP_INDEX) == null)
					s = processIntegerToken(s);
				return Byte.parseByte(s, radix);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a short value in the default radix using the {@link #nextShort}
	 * method. The scanner does not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid short
	 *         value in the default radix
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextShort() {
		try {
			initiateMethodCall("hasNextShort()");
			return hasNextShort(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a short value in the specified radix using the {@link #nextShort}
	 * method. The scanner does not advance past any input.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as a short value
	 * @return true if and only if this scanner's next token is a valid short
	 *         value in the specified radix
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextShort(int radix) {
		try {
			initiateMethodCall("hasNextShort(" + radix + ")");
			setRadix(radix);
			boolean result = hasNext(integerPattern());
			if (result) { // Cache it
				try {
					String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? processIntegerToken(hasNextResult) : hasNextResult;
					typeCache = Short.parseShort(s, radix);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>short</tt>.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>nextShort()</tt> behaves in
	 * exactly the same way as the invocation <tt>nextShort(radix)</tt>, where
	 * <code>radix</code> is the default radix of this scanner.
	 * 
	 * @return the <tt>short</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public short nextShort() {
		try {
			initiateMethodCall("nextShort()");
			return nextShort(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>short</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid short value as described below. If the
	 * translation is successful, the scanner advances past the input that
	 * matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Integer-regex"><i>Integer</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>short</tt> value as if by removing all locale specific prefixes,
	 * group separators, and locale specific suffixes, then mapping non-ASCII
	 * digits into ASCII digits via {@link Character#digit Character.digit},
	 * prepending a negative sign (-) if the locale specific negative prefixes
	 * and suffixes were present, and passing the resulting string to
	 * {@link Short#parseShort(String, int) Short.parseShort} with the specified
	 * radix.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as a short value
	 * @return the <tt>short</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public short nextShort(int radix) {
		try {
			initiateMethodCall("nextShort(" + radix + ")");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Short) && this.radix == radix) {
				short val = ((Short) typeCache).shortValue();
				useTypeCache();
				return val;
			}
			setRadix(radix);
			clearCaches();
			// Search for next short
			try {
				String s = next(integerPattern());
				if (matcher.group(SIMPLE_GROUP_INDEX) == null)
					s = processIntegerToken(s);
				return Short.parseShort(s, radix);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as an int value in the default radix using the {@link #nextInt} method.
	 * The scanner does not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid int
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextInt() {
		try {
			initiateMethodCall("hasNextInt");
			return hasNextInt(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as an int value in the specified radix using the {@link #nextInt} method.
	 * The scanner does not advance past any input.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as an int value
	 * @return true if and only if this scanner's next token is a valid int
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextInt(int radix) {
		try {
			initiateMethodCall("hasNextInt(" + radix + ")");
			setRadix(radix);
			boolean result = hasNext(integerPattern());
			if (result) { // Cache it
				try {
					String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? processIntegerToken(hasNextResult) : hasNextResult;
					typeCache = Integer.parseInt(s, radix);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * The integer token must be stripped of prefixes, group separators, and
	 * suffixes, non ascii digits must be converted into ascii digits before
	 * parse will accept it.
	 */
	private String processIntegerToken(String token) {
		String result = token.replaceAll("" + groupSeparator, "");
		boolean isNegative = false;
		int preLen = negativePrefix.length();
		if ((preLen > 0) && result.startsWith(negativePrefix)) {
			isNegative = true;
			result = result.substring(preLen);
		}
		int sufLen = negativeSuffix.length();
		if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
			isNegative = true;
			result = result.substring(result.length() - sufLen, result.length());
		}
		if (isNegative)
			result = "-" + result;
		return result;
	}

	/**
	 * Scans the next token of the input as an <tt>int</tt>.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>nextInt()</tt> behaves in
	 * exactly the same way as the invocation <tt>nextInt(radix)</tt>, where
	 * <code>radix</code> is the default radix of this scanner.
	 * 
	 * @return the <tt>int</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public int nextInt() {
		try {
			initiateMethodCall("nextInt()");
			return nextInt(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as an <tt>int</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid int value as described below. If the translation
	 * is successful, the scanner advances past the input that matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Integer-regex"><i>Integer</i></a>
	 * regular expression defined above then the token is converted into an
	 * <tt>int</tt> value as if by removing all locale specific prefixes, group
	 * separators, and locale specific suffixes, then mapping non-ASCII digits
	 * into ASCII digits via {@link Character#digit Character.digit}, prepending
	 * a negative sign (-) if the locale specific negative prefixes and suffixes
	 * were present, and passing the resulting string to
	 * {@link Integer#parseInt(String, int) Integer.parseInt} with the specified
	 * radix.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as an int value
	 * @return the <tt>int</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public int nextInt(int radix) {
		try {
			initiateMethodCall("nextInt(" + radix + ")");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Integer) && this.radix == radix) {
				int val = ((Integer) typeCache).intValue();
				useTypeCache();
				return val;
			}
			setRadix(radix);
			clearCaches();
			// Search for next int
			try {
				String s = next(integerPattern());
				if (matcher.group(SIMPLE_GROUP_INDEX) == null)
					s = processIntegerToken(s);
				return Integer.parseInt(s, radix);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a long value in the default radix using the {@link #nextLong} method.
	 * The scanner does not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid long
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextLong() {
		try {
			initiateMethodCall("hasNextLong()");
			return hasNextLong(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a long value in the specified radix using the {@link #nextLong}
	 * method. The scanner does not advance past any input.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as a long value
	 * @return true if and only if this scanner's next token is a valid long
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextLong(int radix) {
		try {
			initiateMethodCall("hasNextLong(" + radix + ")");
			setRadix(radix);
			boolean result = hasNext(integerPattern());
			if (result) { // Cache it
				try {
					String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? processIntegerToken(hasNextResult) : hasNextResult;
					typeCache = Long.parseLong(s, radix);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>long</tt>.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>nextLong()</tt> behaves in
	 * exactly the same way as the invocation <tt>nextLong(radix)</tt>, where
	 * <code>radix</code> is the default radix of this scanner.
	 * 
	 * @return the <tt>long</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public long nextLong() {
		try {
			initiateMethodCall("nextLong()");
			return nextLong(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>long</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid long value as described below. If the translation
	 * is successful, the scanner advances past the input that matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Integer-regex"><i>Integer</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>long</tt> value as if by removing all locale specific prefixes, group
	 * separators, and locale specific suffixes, then mapping non-ASCII digits
	 * into ASCII digits via {@link Character#digit Character.digit}, prepending
	 * a negative sign (-) if the locale specific negative prefixes and suffixes
	 * were present, and passing the resulting string to
	 * {@link Long#parseLong(String, int) Long.parseLong} with the specified
	 * radix.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as an int value
	 * @return the <tt>long</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public long nextLong(int radix) {
		try {
			initiateMethodCall("nextLong(" + radix + ")");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Long) && this.radix == radix) {
				long val = ((Long) typeCache).longValue();
				useTypeCache();
				return val;
			}
			setRadix(radix);
			clearCaches();
			try {
				String s = next(integerPattern());
				if (matcher.group(SIMPLE_GROUP_INDEX) == null)
					s = processIntegerToken(s);
				return Long.parseLong(s, radix);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * The float token must be stripped of prefixes, group separators, and
	 * suffixes, non ascii digits must be converted into ascii digits before
	 * parseFloat will accept it.
	 * 
	 * If there are non-ascii digits in the token these digits must be processed
	 * before the token is passed to parseFloat.
	 */
	private String processFloatToken(String token) {
		String result = token.replaceAll(groupSeparator, "");
		if (!decimalSeparator.equals("\\."))
			result = result.replaceAll(decimalSeparator, ".");
		boolean isNegative = false;
		int preLen = negativePrefix.length();
		if ((preLen > 0) && result.startsWith(negativePrefix)) {
			isNegative = true;
			result = result.substring(preLen);
		}
		int sufLen = negativeSuffix.length();
		if ((sufLen > 0) && result.endsWith(negativeSuffix)) {
			isNegative = true;
			result = result.substring(result.length() - sufLen, result.length());
		}
		if (result.equals(nanString))
			result = "NaN";
		if (result.equals(infinityString))
			result = "Infinity";
		if (isNegative)
			result = "-" + result;

		// Translate non-ASCII digits
		Matcher m = NON_ASCII_DIGIT.matcher(result);
		if (m.find()) {
			StringBuilder inASCII = new StringBuilder();
			for (int i = 0; i < result.length(); i++) {
				char nextChar = result.charAt(i);
				if (Character.isDigit(nextChar)) {
					int d = Character.digit(nextChar, 10);
					if (d != -1)
						inASCII.append(d);
					else
						inASCII.append(nextChar);
				} else {
					inASCII.append(nextChar);
				}
			}
			result = inASCII.toString();
		}

		return result;
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a float value using the {@link #nextFloat} method. The scanner does
	 * not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid float
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextFloat() {
		try {
			initiateMethodCall("hasNextFloat()");
			setRadix(10);
			boolean result = hasNext(floatPattern());
			if (result) { // Cache it
				try {
					String s = processFloatToken(hasNextResult);
					typeCache = Float.valueOf(Float.parseFloat(s));
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>float</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid float value as described below. If the
	 * translation is successful, the scanner advances past the input that
	 * matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Float-regex"><i>Float</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>float</tt> value as if by removing all locale specific prefixes,
	 * group separators, and locale specific suffixes, then mapping non-ASCII
	 * digits into ASCII digits via {@link Character#digit Character.digit},
	 * prepending a negative sign (-) if the locale specific negative prefixes
	 * and suffixes were present, and passing the resulting string to
	 * {@link Float#parseFloat Float.parseFloat}. If the token matches the
	 * localized NaN or infinity strings, then either "Nan" or "Infinity" is
	 * passed to {@link Float#parseFloat(String) Float.parseFloat} as
	 * appropriate.
	 * 
	 * @return the <tt>float</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Float</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public float nextFloat() {
		try {
			initiateMethodCall("nextFloat()");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Float)) {
				float val = ((Float) typeCache).floatValue();
				useTypeCache();
				return val;
			}
			setRadix(10);
			clearCaches();
			try {
				return Float.parseFloat(processFloatToken(next(floatPattern())));
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a double value using the {@link #nextDouble} method. The scanner does
	 * not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid double
	 *         value
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextDouble() {
		try {
			initiateMethodCall("hasNextDouble()");
			setRadix(10);
			boolean result = hasNext(floatPattern());
			if (result) { // Cache it
				try {
					String s = processFloatToken(hasNextResult);
					typeCache = Double.valueOf(Double.parseDouble(s));
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a <tt>double</tt>. This method will
	 * throw <code>InputMismatchException</code> if the next token cannot be
	 * translated into a valid double value. If the translation is successful,
	 * the scanner advances past the input that matched.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Float-regex"><i>Float</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>double</tt> value as if by removing all locale specific prefixes,
	 * group separators, and locale specific suffixes, then mapping non-ASCII
	 * digits into ASCII digits via {@link Character#digit Character.digit},
	 * prepending a negative sign (-) if the locale specific negative prefixes
	 * and suffixes were present, and passing the resulting string to
	 * {@link Double#parseDouble Double.parseDouble}. If the token matches the
	 * localized NaN or infinity strings, then either "Nan" or "Infinity" is
	 * passed to {@link Double#parseDouble(String) Double.parseDouble} as
	 * appropriate.
	 * 
	 * @return the <tt>double</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Float</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if the input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public double nextDouble() {
		try {
			initiateMethodCall("nextDouble()");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof Double)) {
				double val = ((Double) typeCache).doubleValue();
				useTypeCache();
				return val;
			}
			setRadix(10);
			clearCaches();
			// Search for next float
			try {
				return Double.parseDouble(processFloatToken(next(floatPattern())));
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	// Convenience methods for scanning multi precision numbers

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a <code>BigInteger</code> in the default radix using the
	 * {@link #nextBigInteger} method. The scanner does not advance past any
	 * input.
	 * 
	 * @return true if and only if this scanner's next token is a valid
	 *         <code>BigInteger</code>
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextBigInteger() {
		try {
			initiateMethodCall("hasNextBigInteger()");
			return hasNextBigInteger(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a <code>BigInteger</code> in the specified radix using the
	 * {@link #nextBigInteger} method. The scanner does not advance past any
	 * input.
	 * 
	 * @param radix
	 *            the radix used to interpret the token as an integer
	 * @return true if and only if this scanner's next token is a valid
	 *         <code>BigInteger</code>
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextBigInteger(int radix) {
		try {
			initiateMethodCall("hasNextBigInteger(" + radix + ")");
			setRadix(radix);
			boolean result = hasNext(integerPattern());
			if (result) { // Cache it
				try {
					String s = (matcher.group(SIMPLE_GROUP_INDEX) == null) ? processIntegerToken(hasNextResult) : hasNextResult;
					typeCache = new BigInteger(s, radix);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a {@link java.math.BigInteger
	 * BigInteger}.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>nextBigInteger()</tt>
	 * behaves in exactly the same way as the invocation
	 * <tt>nextBigInteger(radix)</tt>, where <code>radix</code> is the default
	 * radix of this scanner.
	 * 
	 * @return the <tt>BigInteger</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if the input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public BigInteger nextBigInteger() {
		try {
			initiateMethodCall("nextBigInteger()");
			return nextBigInteger(defaultRadix);
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a {@link java.math.BigInteger
	 * BigInteger}.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Integer-regex"><i>Integer</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>BigInteger</tt> value as if by removing all group separators, mapping
	 * non-ASCII digits into ASCII digits via the {@link Character#digit
	 * Character.digit}, and passing the resulting string to the
	 * {@link java.math.BigInteger#BigInteger(java.lang.String)
	 * BigInteger(String, int)} constructor with the specified radix.
	 * 
	 * @param radix
	 *            the radix used to interpret the token
	 * @return the <tt>BigInteger</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Integer</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if the input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public BigInteger nextBigInteger(int radix) {
		try {
			initiateMethodCall("nextBigInteger(" + radix + ")");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof BigInteger) && this.radix == radix) {
				BigInteger val = (BigInteger) typeCache;
				useTypeCache();
				return val;
			}
			setRadix(radix);
			clearCaches();
			// Search for next int
			try {
				String s = next(integerPattern());
				if (matcher.group(SIMPLE_GROUP_INDEX) == null)
					s = processIntegerToken(s);
				return new BigInteger(s, radix);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Returns true if the next token in this scanner's input can be interpreted
	 * as a <code>BigDecimal</code> using the {@link #nextBigDecimal} method.
	 * The scanner does not advance past any input.
	 * 
	 * @return true if and only if this scanner's next token is a valid
	 *         <code>BigDecimal</code>
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public boolean hasNextBigDecimal() {
		try {
			initiateMethodCall("hasNextBigDecimal()");
			setRadix(10);
			boolean result = hasNext(decimalPattern());
			if (result) { // Cache it
				try {
					String s = processFloatToken(hasNextResult);
					typeCache = new BigDecimal(s);
				} catch (NumberFormatException nfe) {
					result = false;
				}
			}
			return result;
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Scans the next token of the input as a {@link java.math.BigDecimal
	 * BigDecimal}.
	 * 
	 * <p>
	 * If the next token matches the <a href="#Decimal-regex"><i>Decimal</i></a>
	 * regular expression defined above then the token is converted into a
	 * <tt>BigDecimal</tt> value as if by removing all group separators, mapping
	 * non-ASCII digits into ASCII digits via the {@link Character#digit
	 * Character.digit}, and passing the resulting string to the
	 * {@link java.math.BigDecimal#BigDecimal(java.lang.String)
	 * BigDecimal(String)} constructor.
	 * 
	 * @return the <tt>BigDecimal</tt> scanned from the input
	 * @throws InputMismatchException
	 *             if the next token does not match the <i>Decimal</i> regular
	 *             expression, or is out of range
	 * @throws NoSuchElementException
	 *             if the input is exhausted
	 * @throws IllegalStateException
	 *             if this scanner is closed
	 */
	public BigDecimal nextBigDecimal() {
		try {
			initiateMethodCall("nextBigDecimal()");
			// Check cached result
			if ((typeCache != null) && (typeCache instanceof BigDecimal)) {
				BigDecimal val = (BigDecimal) typeCache;
				useTypeCache();
				return val;
			}
			setRadix(10);
			clearCaches();
			// Search for next float
			try {
				String s = processFloatToken(next(decimalPattern()));
				return new BigDecimal(s);
			} catch (NumberFormatException nfe) {
				position = matcher.start(); // don't skip bad token
				throw new InputMismatchException(nfe.getMessage());
			} finally {

			}
		} finally {
			finalizeMethodCall();
		}
	}

	/**
	 * Resets this scanner.
	 * 
	 * <p>
	 * Resetting a scanner discards all of its explicit state information which
	 * may have been changed by invocations of {@link #useDelimiter},
	 * {@link #useLocale}, or {@link #useRadix}.
	 * 
	 * <p>
	 * An invocation of this method of the form <tt>scanner.reset()</tt> behaves
	 * in exactly the same way as the invocation
	 * 
	 * <blockquote>
	 * 
	 * <pre>
	 * scanner.useDelimiter(&quot;\\p{javaWhitespace}+&quot;).useLocale(Locale.getDefault()).useRadix(10);
	 * </pre>
	 * 
	 * </blockquote>
	 * 
	 * @return this scanner
	 * 
	 * @since 1.6
	 */
	public VisualScanner reset() {
		try {
			initiateMethodCall("reset()");
			delimPattern = WHITESPACE_PATTERN;
			useLocale(Locale.getDefault());
			useRadix(10);
			clearCaches();
			return this;
		} finally {
			finalizeMethodCall();
		}
	}

	// ----------------------------------------------------------------------
	// Instance variables and methods for visualizing the current state of
	// this scanner.
	// ----------------------------------------------------------------------

	// Frame displaying internal content of this scanner
	private volatile ScannerFrame frame;

	// Number of methods which were started but not finalized.
	private int openMethodsCount = 0;

	// Indicates that all calls that will be executed are private from
	// ScannerFrame
	private boolean privateCalls = false;

	// Wait lock used to block the current thread until the user permits to
	// continue
	final Object waitLock = new Object();

	// Description of the scanner source
	volatile String sourceDescription;

	// Name of operation (method) that will executed after confirmation
	volatile String currentOperation;

	/**
	 * Initializes an execution of a scanner method. This methods is called at
	 * the beginning of each public method of the scanner that is related to
	 * scanning the content.
	 * 
	 * @param method
	 *            name of the called method
	 */
	private void initiateMethodCall(String method) {
		// if this is a call that is a result of visualization actions, we do
		// nothing
		if (privateCalls)
			return;

		openMethodsCount++;

		// if this is the first "public" call, we show the window and update its
		// state
		if (openMethodsCount == 1) {
			currentOperation = method;
			updateVisualizationFrame();
			// wait for confirmation of the user to execute this method
			waitForPermission();
		}
	}

	/**
	 * Finalizes an execution of a scanner method. This methods is called in the
	 * finally block of each public method of the scanner that is related to
	 * scanning the content.
	 */
	private void finalizeMethodCall() {
		// if this is a call that is a result of visualization actions, we do
		// nothing
		if (privateCalls)
			return;

		openMethodsCount--;

		// if number of finalization reached 0, we update the visualization
		// frame
		if (openMethodsCount == 0) {
			currentOperation = null;
			if (EventQueue.isDispatchThread()) {
				throw new RuntimeException("Methods of VisualScanner cannot be called from the Event Dispatch Thread.");
			}
			updateVisualizationFrame();
		}
	}

	/**
	 * Block the current thread until an action is confirmed by the user in the
	 * visualization frame.
	 */
	private void waitForPermission() {
		synchronized (waitLock) {
			try {
				waitLock.wait();
			} catch (InterruptedException ignore) {
			}
		}
	}

	/**
	 * Updates the visualization frame.
	 */
	private void updateVisualizationFrame() {
		// set that all next method invocations of Scanner are private (not
		// realized by the user code)
		privateCalls = true;

		// realized the update of the visualization frame in the EDT
		try {
			EventQueue.invokeAndWait(new Runnable() {
				public void run() {
					// if the scanner is closed, we close the frame
					if (closed) {
						if (frame != null) {
							frame.setVisible(false);
							frame.dispose();
						}

						return;
					}

					// create a new frame, if this is the first operation
					if (frame == null) {
						try {
							UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
						} catch (Exception ignore) {
						}
						frame = new ScannerFrame(VisualScanner.this);
						frame.setLocationRelativeTo(null);
					}

					// update scanner view
					frame.updateView();

					// ensure that the view is visible
					frame.setVisible(true);
				}
			});
		} catch (Exception ignore) {

		}

		// set that all next method invocations are caused by the user code
		privateCalls = false;
	}

	/**
	 * Returns a next token to be scanned by the scanner.
	 */
	String getNextToken() {
		if (!hasNext()) {
			return null;
		}

		saveState();
		String result = next();
		revertState();

		return result;
	}

	/**
	 * Returns the unscanned content in the buffer of this scanner.
	 */
	String getBuffer() {
		if (buf != null) {
			return buf.subSequence(position, buf.limit()).toString();
		} else {
			return null;
		}
	}
}
